package org.example.ItemCF.src.recommend;

/**
 * Step2UserVectorToCooccurrenceMapper
 *
 * @author waqwb
 * @since 2024/4/16
 */

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * 映射器类：将用户向量转换为项目对的共现记录。
 */
public class Step2UserVectorToCooccurrenceMapper extends
        Mapper<LongWritable, Text, Text, IntWritable> {
    private final static Text k = new Text();
    private final static IntWritable v = new IntWritable(1);

    /**
     * 映射函数：生成项目对及其共现计数。
     * 此函数用于MapReduce框架中，针对输入的每条记录（用户偏好向量），将其分割，并生成所有可能的项目对。
     * 对于每个项目对，将其作为键，输出到下一阶段的Reduce任务中。
     *
     * @param key 输入记录的键，通常代表一行数据的唯一标识。
     * @param values 输入记录的值，包含了用户的偏好向量信息。
     * @param context 上下文对象，用于输出键值对到Reduce任务。
     * @throws IOException 当读取或写入发生错误时抛出。
     * @throws InterruptedException 当执行被中断时抛出。
     */
    @Override
    public void map(LongWritable key, Text values, Context context)
            throws IOException, InterruptedException {
        // 分割用户偏好向量，并生成项目对
        String[] tokens = Recommend.DELIMITER.split(values.toString());
        // 遍历所有tokens中的项目对，并为其设置键，然后输出键值对
        for (int i = 1; i < tokens.length; i++) {
            String itemID = tokens[i].split(":")[0]; // 获取当前token的第一个部分作为项目ID
            for (int j = 1; j < tokens.length; j++) { // 遍历所有其他token以生成项目对
                String itemID2 = tokens[j].split(":")[0]; // 获取当前token的第一个部分作为另一个项目ID
                k.set(itemID + ":" + itemID2); // 设置键为项目对
                context.write(k, v); // 输出项目对及其计数
            }
        }

    }

}
   
